package com.jevons.geo_lib.geo_op;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.view.View;

import androidx.annotation.NonNull;

import com.google.gson.JsonObject;
import com.jevons.geo_lib.R;
import com.jevons.geo_lib.dialog.SimpleDialog;
import com.jevons.geo_lib.geojson.MapboxJsonHelper;
import com.jevons.geo_lib.helper.GeometryHelper;
import com.jevons.geo_lib.op_history.BianjieCommonHistory;
import com.jevons.geo_lib.op_history.BianjieHistory;
import com.jevons.geo_lib.op_history.DrawType;
import com.jevons.geo_lib.op_history.HebingHistory;
import com.jevons.geo_lib.op_history.HuizhiHistory;
import com.jevons.geo_lib.op_history.OperationHistory;
import com.jevons.geo_lib.op_history.QiegeHistory;
import com.jevons.geo_lib.op_history.ShanchuHistory;
import com.jevons.geo_lib.op_history.WakongHistory;
import com.jevons.geo_lib.utils.ImageUtils;
import com.jevons.geo_lib.utils.StringUtils;
import com.jevons.geo_lib.view.BaseMapView;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Geometry;
import com.mapbox.geojson.LineString;
import com.mapbox.geojson.MultiPolygon;
import com.mapbox.geojson.Point;
import com.mapbox.geojson.Polygon;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.plugins.annotation.OnSymbolDragListener;
import com.mapbox.mapboxsdk.plugins.annotation.OnSymbolLongClickListener;
import com.mapbox.mapboxsdk.plugins.annotation.Symbol;
import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager;
import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.turf.TurfMeasurement;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.functions.Function;
import io.reactivex.observers.DisposableObserver;

/**
 * Copyright 2020 JxGIS
 *
 * @file GeometryOpManager
 * @auth linaisheng
 * Created on 2022/9/20.
 * Description：
 */
public class GeometryOpManager implements OnSymbolDragListener, OnSymbolLongClickListener {

    public enum OpGeometryType {
        Point,
        Line,
        Polygon
    }


    //选中图形图层
    private static final String SOURCE_SELECTED_EDIT_GEOMETRY = "selected_edit_geometry_source";
    private static final String LAYER_FILL_SELECTED_EDIT_GEOMETRY = "selected_edit_geometry_fill_layer";
    private static final String LAYER_LINE_SELECTED_EDIT_GEOMETRY = "selected_edit_geometry_line_layer";
    private static final String LAYER_POINT_SELECTED_EDIT_GEOMETRY = "selected_edit_geometry_point_layer";

    //图形操作结果图层
    public static final String SOURCE_OP_EDIT_RESULT = "op_edit_result_source";
    public static final String LAYER_OP_EDIT_RESULT_FILL = "op_edit_result_fill";
    public static final String LAYER_OP_EDIT_RESULT_LINE = "op_edit_result_line";
    public static final String LAYER_OP_EDIT_RESULT_POINT = "op_edit_result_point";

    //操作图层
    public static final String SOURCE_OP_EDIT = "op_edit_source";
    public static final String LAYER_OP_EDIT_FILL_LAYER = "op_edit_fill";
    public static final String LAYER_OP_EDIT_LINE_LAYER = "op_edit_line";
    public static final String LAYER_OP_EDIT_POINT_LAYER = "op_edit_point";



    //被选中的点图标
    public static final String ICON_POINT_SELECTED_EDIT_GEOMETRY = "icon_point_selected_edit_geometry";
    public static final String ICON_POINT_SELECTED_EDIT_GEOMETRY_CUSTOM = "icon_point_selected_edit_geometry_custom";

    public static final String ICON_POINT_EDIT_RESULT_GEOMETRY = "icon_point_edit_result_geometry";
    public static final String ICON_POINT_EDIT_RESULT_GEOMETRY_CUSTOM = "icon_point_edit_result_geometry_custom";

    public static String KEY_FEATURE_ID = "id";
    public static final String KEY_FEATURE_TEMP_ID = "temp_id";




    private BaseMapView baseView;
    private MapView mMapView;
    private MapboxMap mMapboxMap;
    private Style loadStyle;

    private GeometrySymbolHandler symbolHandler;

    private OpGeometryType geometryType = OpGeometryType.Polygon;

    private GeoJsonSource selectedEditGeometrySource;
    private Feature selectedEditFeature;

    private List<Feature> editFeatures;

    private GeoJsonSource geoOpEditResultSource;
    private GeoJsonSource geoOpEditSource;

    private Set<String> storeFeatureIds = new HashSet<>();
    private List<Feature> storeFeatureList = new ArrayList<>();
    private List<Point> storePointList = new ArrayList<>();

    private DrawType drawModel = DrawType.None;

    private GeometryOpListener opListener;

    //历史操作记录
    private Stack<OperationHistory> historyOperationStack = new Stack<>();
    //存储回撤的历史操作记录，用于返回重做操作
    private Stack<OperationHistory> undoHistoryOperationStack = new Stack<>();

    //操作保存时存储的操作结果
    private List<GeoOpSaveResult> saveResultList = new ArrayList<>();

    public GeometryOpManager(BaseMapView baseView, MapView mapView, MapboxMap mapboxMap, Style style) {
        this.baseView = baseView;
        this.mMapView = mapView;
        this.mMapboxMap = mapboxMap;
        this.loadStyle = style;



        symbolHandler = new GeometrySymbolHandler(
                this,  new SymbolManager(mMapView, mMapboxMap, loadStyle));
        symbolHandler.addPointImage(loadStyle, mapView.getResources());
    }

    BaseMapView getBaseView() {
        return baseView;
    }

    public static void setFeatureIdKey(String key) {
        KEY_FEATURE_ID = key;
    }

    public void addGeoOperationLayer(String aboveLayer) {

        //选中图形的图层样式
        OperationLayerStyle selectedEditLayerStyle = new OperationLayerStyle(
                "#FF0000", 0.6f, "#FFFF00", 1f, 3f);

        //保存结果的图像样式
        OperationLayerStyle editResultLayerStyle = new OperationLayerStyle(
                "#5086C2", 0.6f, "#5086C2", 1f, 3f);

        //操作绘制时的图像样式
        OperationLayerStyle editLayerStyle = new OperationLayerStyle(
                "#D5E82B", 0.6f, "#D5E82B", 1f, 3f);

        addGeoOperationLayer(aboveLayer, selectedEditLayerStyle, editResultLayerStyle, editLayerStyle);
    }

    public void addGeoOperationLayer(
            String aboveLayer,
            OperationLayerStyle selectedEditLayerStyle,
            OperationLayerStyle editResultLayerStyle,
            OperationLayerStyle editLayerStyle) {
        editFeatures = new ArrayList<>();

        selectedEditGeometrySource = new GeoJsonSource(SOURCE_SELECTED_EDIT_GEOMETRY);
        loadStyle.addSource(selectedEditGeometrySource);

        loadStyle.addImage(ICON_POINT_SELECTED_EDIT_GEOMETRY, ImageUtils.makeTintBitmap(
                BitmapFactory.decodeResource(mMapView.getResources(),
                        R.mipmap.icon_geo_point_layer_default),
                Color.parseColor(selectedEditLayerStyle.getFillColor())));

        FillLayer fillLayer = new FillLayer(LAYER_FILL_SELECTED_EDIT_GEOMETRY, SOURCE_SELECTED_EDIT_GEOMETRY)
                .withFilter(
                        Expression.any(
                                Expression.eq(Expression.geometryType(), "Polygon"),
                                Expression.eq(Expression.geometryType(), "MultiPolygon"))
                )
                .withProperties(
                        PropertyFactory.fillColor(selectedEditLayerStyle.getFillColor()),
                        PropertyFactory.fillOpacity(selectedEditLayerStyle.getFillOpacity())
                );
        loadStyle.addLayerAbove(fillLayer, aboveLayer);

        LineLayer lineLayer = new LineLayer(LAYER_LINE_SELECTED_EDIT_GEOMETRY, SOURCE_SELECTED_EDIT_GEOMETRY)
                .withFilter(Expression.any(
                        Expression.eq(Expression.geometryType(), "LineString"),
                        Expression.eq(Expression.geometryType(), "MultiLineString"),
                        Expression.eq(Expression.geometryType(), "Polygon"),
                        Expression.eq(Expression.geometryType(), "MultiPolygon")
                ))
                .withProperties(
                        PropertyFactory.lineColor(Expression.switchCase(
                                Expression.eq(Expression.geometryType(), "LineString"), Expression.color(Color.parseColor(selectedEditLayerStyle.getFillColor())),
                                Expression.eq(Expression.geometryType(), "MultiLineString"), Expression.color(Color.parseColor(selectedEditLayerStyle.getFillColor())),
                                Expression.color(Color.parseColor(selectedEditLayerStyle.getLineColor()))
                        )),
                        PropertyFactory.lineOpacity(selectedEditLayerStyle.getLineOpacity()),
                        PropertyFactory.lineWidth(selectedEditLayerStyle.getLineWidth())
                );
        loadStyle.addLayerAbove(lineLayer, LAYER_FILL_SELECTED_EDIT_GEOMETRY);

        SymbolLayer symbolLayer = new SymbolLayer(LAYER_POINT_SELECTED_EDIT_GEOMETRY, SOURCE_SELECTED_EDIT_GEOMETRY)
                .withFilter(Expression.any(
                        Expression.eq(Expression.geometryType(), "Point"),
                        Expression.eq(Expression.geometryType(), "MultiPoint")
                ))
                .withProperties(
                        PropertyFactory.iconImage(ICON_POINT_SELECTED_EDIT_GEOMETRY),
                        PropertyFactory.iconSize(selectedEditLayerStyle.getIconSize()),
                        PropertyFactory.iconAllowOverlap(true)
                );
        loadStyle.addLayerAbove(symbolLayer, LAYER_LINE_SELECTED_EDIT_GEOMETRY);



        //操作结果
        geoOpEditResultSource = new GeoJsonSource(SOURCE_OP_EDIT_RESULT);
        loadStyle.addSource(geoOpEditResultSource);


        loadStyle.addImage(ICON_POINT_EDIT_RESULT_GEOMETRY, ImageUtils.makeTintBitmap(
                BitmapFactory.decodeResource(mMapView.getResources(),
                        R.mipmap.icon_geo_point_layer_default),
                Color.parseColor(editResultLayerStyle.getFillColor())));

        loadStyle.addLayerAbove(new FillLayer(LAYER_OP_EDIT_RESULT_FILL, SOURCE_OP_EDIT_RESULT)
                        .withFilter(
                                Expression.any(
                                        Expression.eq(Expression.geometryType(), "Polygon"),
                                        Expression.eq(Expression.geometryType(), "MultiPolygon"))
                        )
                        .withProperties(
                                PropertyFactory.fillColor(editResultLayerStyle.getFillColor()),
                                PropertyFactory.fillOpacity(editResultLayerStyle.getFillOpacity())),
                LAYER_POINT_SELECTED_EDIT_GEOMETRY);
        loadStyle.addLayerAbove(new LineLayer(LAYER_OP_EDIT_RESULT_LINE, SOURCE_OP_EDIT_RESULT)
                        .withFilter(Expression.any(
                                Expression.eq(Expression.geometryType(), "LineString"),
                                Expression.eq(Expression.geometryType(), "MultiLineString"),
                                Expression.eq(Expression.geometryType(), "Polygon"),
                                Expression.eq(Expression.geometryType(), "MultiPolygon")
                        ))
                        .withProperties(
                                PropertyFactory.lineColor(editResultLayerStyle.getLineColor()),
                                PropertyFactory.lineOpacity(editResultLayerStyle.getLineOpacity()),
                                PropertyFactory.lineWidth(editResultLayerStyle.getLineWidth())),
                LAYER_OP_EDIT_RESULT_FILL);
        loadStyle.addLayerAbove(new SymbolLayer(LAYER_OP_EDIT_RESULT_POINT, SOURCE_OP_EDIT_RESULT)
                        .withFilter(
                                Expression.any(
                                        Expression.eq(Expression.geometryType(), "Point"),
                                        Expression.eq(Expression.geometryType(), "MultiPoint"))
                        )
                        .withProperties(
                                PropertyFactory.iconImage(ICON_POINT_EDIT_RESULT_GEOMETRY),
                                PropertyFactory.iconSize(editResultLayerStyle.getIconSize()),
                                PropertyFactory.iconAllowOverlap(true)),
                LAYER_OP_EDIT_RESULT_LINE);


        //操作图形
        geoOpEditSource = new GeoJsonSource(SOURCE_OP_EDIT);
        loadStyle.addSource(geoOpEditSource);
        loadStyle.addLayerAbove(new FillLayer(LAYER_OP_EDIT_FILL_LAYER, SOURCE_OP_EDIT)
                        .withFilter(
                                Expression.any(
                                        Expression.eq(Expression.geometryType(), "Polygon"),
                                        Expression.eq(Expression.geometryType(), "MultiPolygon"))
                        )
                        .withProperties(
                                PropertyFactory.fillColor(editLayerStyle.getFillColor()),
                                PropertyFactory.fillOpacity(editLayerStyle.getFillOpacity())),
                LAYER_OP_EDIT_RESULT_POINT);
        loadStyle.addLayerAbove(new LineLayer(LAYER_OP_EDIT_LINE_LAYER, SOURCE_OP_EDIT)
                        .withFilter(Expression.any(
                                Expression.eq(Expression.geometryType(), "LineString"),
                                Expression.eq(Expression.geometryType(), "MultiLineString"),
                                Expression.eq(Expression.geometryType(), "Polygon"),
                                Expression.eq(Expression.geometryType(), "MultiPolygon")
                        ))
                        .withProperties(
                                PropertyFactory.lineColor(editLayerStyle.getLineColor()),
                                PropertyFactory.lineOpacity(editLayerStyle.getLineOpacity()),
                                PropertyFactory.lineWidth(editLayerStyle.getLineWidth())),
                LAYER_OP_EDIT_FILL_LAYER);
        loadStyle.addLayerAbove(new SymbolLayer(LAYER_OP_EDIT_POINT_LAYER, SOURCE_OP_EDIT)
                        .withFilter(Expression.any(
                                Expression.any(
                                        Expression.eq(Expression.geometryType(), "Point"),
                                        Expression.eq(Expression.geometryType(), "MultiPoint"))
                        ))
                        .withProperties(
                                PropertyFactory.iconImage(ICON_POINT_EDIT_RESULT_GEOMETRY),
                                PropertyFactory.iconSize(editResultLayerStyle.getIconSize()),
                                PropertyFactory.iconAllowOverlap(true)),
                LAYER_OP_EDIT_LINE_LAYER);
    }


    public void updateSelectedEditPointLayerStyle(Bitmap iconBitmap, float iconSize) {
        Layer selectedEditPointLayer = loadStyle.getLayer(LAYER_POINT_SELECTED_EDIT_GEOMETRY);
        if (selectedEditPointLayer != null) {
            if (iconBitmap != null) {
                Bitmap bitmap = ImageUtils.makeTintBitmap(iconBitmap,
                        Color.parseColor("#FF0000"));
                loadStyle.addImage(ICON_POINT_SELECTED_EDIT_GEOMETRY_CUSTOM, bitmap);
                selectedEditPointLayer.setProperties(
                        PropertyFactory.iconImage(ICON_POINT_SELECTED_EDIT_GEOMETRY_CUSTOM),
                        PropertyFactory.iconSize(iconSize));
            } else {
                selectedEditPointLayer.setProperties(
                        PropertyFactory.iconImage(ICON_POINT_SELECTED_EDIT_GEOMETRY),
                        PropertyFactory.iconSize(0.5f));
            }
        }


    }

    public void updateOpEditPointLayerStyle(Bitmap iconBitmap, float iconSize) {
        Layer opEditPointLayer = loadStyle.getLayer(LAYER_OP_EDIT_POINT_LAYER);
        if (opEditPointLayer != null) {
            if (iconBitmap != null) {
                Bitmap bitmap = ImageUtils.makeTintBitmap(iconBitmap,
                        Color.parseColor("#D5E82B"));
                loadStyle.addImage(ICON_POINT_EDIT_RESULT_GEOMETRY_CUSTOM, bitmap);
                opEditPointLayer.setProperties(
                        PropertyFactory.iconImage(ICON_POINT_EDIT_RESULT_GEOMETRY_CUSTOM),
                        PropertyFactory.iconSize(iconSize));
            } else {
                opEditPointLayer.setProperties(
                        PropertyFactory.iconImage(ICON_POINT_EDIT_RESULT_GEOMETRY),
                        PropertyFactory.iconSize(0.5f));
            }
        }
    }

    public void setGeometryOpListener(GeometryOpListener opListener) {
        this.opListener = opListener;
    }

    public void setSelectedEditGeometryLayerVisible(boolean isVisible) {
        String[] layerIds = {
                LAYER_FILL_SELECTED_EDIT_GEOMETRY,
                LAYER_LINE_SELECTED_EDIT_GEOMETRY,
                LAYER_POINT_SELECTED_EDIT_GEOMETRY
        };
        for (String layerId : layerIds) {
            Layer layer = loadStyle.getLayer(layerId);
            if (layer != null) {
                layer.setProperties(PropertyFactory.visibility(isVisible ? Property.VISIBLE : Property.NONE));
            }
        }
    }

    public void setGeometryType(OpGeometryType geometryType) {
        this.geometryType = geometryType;
    }

    public void setSelectedEditFeature(Feature editFeature) {
        if (editFeature != null) {
            //深复制
            selectedEditFeature = Feature.fromJson(MapboxJsonHelper.featureToJson(editFeature));
            selectedEditGeometrySource.setGeoJson(selectedEditFeature);
        } else {
            selectedEditFeature = null;
            selectedEditGeometrySource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
        }
    }

    public Feature getSelectedEditFeature() {
        return selectedEditFeature;
    }

    public String getSelectedEditFeatureId() {
        Feature feature = getSelectedEditFeature();
        if (feature != null) {
            return feature.getStringProperty(KEY_FEATURE_ID);
        }
        return null;
    }

    private void setEditFeature(Feature editFeature) {
        editFeatures.clear();
        if (editFeature != null) {
            //深复制，避免影响到原始数据
            Feature copyFeature = Feature.fromJson(MapboxJsonHelper.featureToJson(editFeature));
            editFeatures.add(copyFeature);
        }
    }


    public DrawType getDrawModel() {
        return drawModel;
    }

    public Feature getEditFeature() {
        if (editFeatures.size() > 0) {
            return editFeatures.get(0);
        }
        return null;
    }

    private String getEditFeatureId() {
        Feature feature = getEditFeature();
        if (feature != null) {
            return feature.getStringProperty(KEY_FEATURE_ID);
        }
        return null;
    }

    Feature getEditFeature(String id) {
        for (Feature feature : editFeatures) {
            if (feature.hasProperty(KEY_FEATURE_ID)
                    && feature.getStringProperty(KEY_FEATURE_ID).equals(id)) {
                return feature;
            }
        }
        return null;
    }

    public List<Feature> getEditFeatures() {
        return editFeatures;
    }


    public void clickTopicOp(DrawType drawType) {
        if (drawModel == DrawType.None) {
            if (selectedEditFeature == null
                    && (drawType == DrawType.Bianjie
                    || drawType == DrawType.Qiege
                    || drawType == DrawType.Wakong
                    || drawType == DrawType.Hebing)) {
                baseView.showToast("请先选中图形");
                return;
            } else {
                setEditFeature(selectedEditFeature);
                entryDrawModel(drawType);
            }
        } else if (drawModel == drawType) {
            //关闭当前模式
            exitDrawModel();
            if (opListener != null) {
                opListener.entryGeoEditModel(DrawType.None);
            }
        } else {
            //切换到其他模式

        }
    }

    private void entryDrawModel(DrawType drawType) {
        saveResultList.clear();
        if (drawType == DrawType.Shanchu && getSelectedEditFeature() != null) {
            addShanchuFeature(getSelectedEditFeature());
        }
        if (drawType == DrawType.Huizhi || drawType == DrawType.Shanchu) {
            setSelectedEditFeature(null);
            setEditFeature(null);
        }
        drawModel = drawType;
        if (opListener != null) {
            opListener.entryGeoEditModel(drawModel);
        }

        if (drawModel == DrawType.Bianjie) {
            addBianjieFeature(selectedEditFeature);
        }
    }

    private void exitDrawModel() {
        if (drawModel != DrawType.Bianjie) {
            doClearOperation();
        } else {
            symbolHandler.clearAllSymbol();
            historyOperationStack = new Stack<>();

            symbolHandler.clearCommonPointData();

            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
        }
        setOpEditResults(null);
        if (opListener != null) {
            opListener.existGeoEditModel(drawModel);
        }
        drawModel = DrawType.None;
        saveResultList.clear();
    }

    void addBianjieFeature(Feature feature) {
        geoOpEditSource.setGeoJson(feature);
        symbolHandler.addBianjieFeatureSymbolPoint(feature, new GeometrySymbolHandler.OnAddBianjieFeatureSymbolPointListener() {
            @Override
            public void onLoadSuccess() {
                doQueryBianjieCommonPoint(feature);
            }
        });
    }

    private void doQueryBianjieCommonPoint(Feature feature) {
        Observable<Feature> observable = queryCommonPointGeometry(feature);
        if (observable != null) {
            observable.map(new Function<Feature, Feature>() {
                @Override
                public Feature apply(@NonNull Feature feature) throws Exception {
                    //深复制
                    Feature copy = Feature.fromJson(MapboxJsonHelper.featureToJson(feature));
                    return copy;
                }
            }).subscribe(new BianjieCommonPointObserver());
        }
    }

    public Observable<Feature> queryCommonPointGeometry(Feature feature) {
        return null;
    }



    private void setOpEditResult(Feature feature) {
        if (feature != null) {
            editFeatures.clear();
            editFeatures.add(feature);
            geoOpEditResultSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
            if (opListener != null) {
                opListener.onCompleteStateChange(drawModel,true);
            }
        } else {
            geoOpEditResultSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
            if (opListener != null) {
                opListener.onCompleteStateChange(drawModel,false);
            }
        }
    }

    private void setOpEditResults(List<Feature> features) {
        if (features != null) {
            editFeatures = features;
            geoOpEditResultSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
            if (opListener != null) {
                opListener.onCompleteStateChange(drawModel,true);
            }
        } else {
            geoOpEditResultSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
            if (opListener != null) {
                opListener.onCompleteStateChange(drawModel, false);
            }
        }
    }

    private void addOpEditResults(List<Feature> features) {
        if (features != null) {
            editFeatures.addAll(features);
            geoOpEditResultSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
        }
    }

    private boolean hasOpEditResult() {
        //to do 理论上features是只有一条记录，但mapbox能查询出多条，待考证
        List<Feature> features = geoOpEditResultSource.querySourceFeatures(Expression.all());
        if (features.size() > 0) {
            return true;
        }
        return false;
    }


    public void dealMapClick(LatLng latLng) {
        if (drawModel == DrawType.Huizhi) {
            boolean hasResult = hasOpEditResult();
            if (hasResult) {
                //设置结果后不可以继续描点

            } else {
                addHuizhiPoint(latLng);
            }
        }
        else if (drawModel == DrawType.Bianjie) {

        } else if (drawModel == DrawType.Qiege) {
            addQiegePoint(latLng);
        }
        else if (drawModel == DrawType.Wakong) {
            addWakongPoint(latLng);
        }
        else if (drawModel == DrawType.Hebing) {
            queryMapFeature(latLng, new DisposableObserver<Feature>(){
                @Override
                public void onNext(@NonNull Feature feature) {
                    if (feature != null) {
                        //判断查询出来的是否跟选中的一致
                        String queryId = feature.getStringProperty(KEY_FEATURE_ID);
                        if (!queryId.equals(getSelectedEditFeatureId())) {
                            addHebingFeature(feature);
                        }
                    }
                }

                @Override
                public void onError(@NonNull Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });
        }
        else if (drawModel == DrawType.Shanchu) {
            queryMapFeature(latLng, new DisposableObserver<Feature>() {
                @Override
                public void onNext(@NonNull Feature feature) {
                    addShanchuFeature(feature);
                }

                @Override
                public void onError(@NonNull Throwable e) {

                }

                @Override
                public void onComplete() {

                }
            });
        }

    }

    private void queryMapFeature(LatLng latLng, DisposableObserver<Feature> observable) {
        Observable<Feature> obser = queryMapFeature(latLng);
        if (obser != null) {
            obser.map(new Function<Feature, Feature>() {
                @Override
                public Feature apply(@NonNull Feature realFeature) throws Exception {
                    //深度复制
                    String featureId = realFeature.getStringProperty(KEY_FEATURE_ID);
                    Feature copyFeature = Feature.fromJson(
                            MapboxJsonHelper.featureToJson(realFeature));
                    copyFeature.addStringProperty(KEY_FEATURE_ID, featureId);
                    return copyFeature;
                }
            }).subscribe(observable);
        }
    }

    public Observable<Feature> queryMapFeature(LatLng latLng) {
        return null;
    }


    void addHuizhiPoint(LatLng latLng) {
        if (isFastDrag) {
            //消费快速拖拽问题
            isFastDrag = false;
            return;
        }

        Point prePoint = null;
        if (storePointList.size() > 0) {
            prePoint = storePointList.get(storePointList.size() - 1);
        }
        Point point = Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude());
        if (geometryType == OpGeometryType.Polygon) {
            //绘制多边形
            storePointList.add(point);

            symbolHandler.addPointSymbolOnHuizhi(geometryType, storePointList, point);

            List<Point> points = new ArrayList<>();
            points.addAll(storePointList);
            //闭合
            points.add(points.get(0));

            List<List<Point>> data = new ArrayList<>();
            data.add(points);
            geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));
        } else if (geometryType == OpGeometryType.Line) {
            storePointList.add(point);

            symbolHandler.addPointSymbolOnHuizhi(geometryType, storePointList, point);

            geoOpEditSource.setGeoJson(LineString.fromLngLats(new ArrayList<>(storePointList)));
        } else if (geometryType == OpGeometryType.Point) {
            //删除前一个点
            storePointList.clear();

            symbolHandler.clearPointSymbol();

            storePointList.add(point);

            symbolHandler.createSymbol(latLng, storePointList.size() - 1);
        }


        HuizhiHistory huizhiHistory = new HuizhiHistory(
                HuizhiHistory.Type.AddPoint, storePointList.size() - 1, point);
        huizhiHistory.setOldPoint(prePoint);

        historyOperationStack.push(huizhiHistory);
        undoHistoryOperationStack.clear();
    }


    //添加周边相交小班
    void addBianjieBoundaryFeature(List<Feature> featureCollection) {
        editFeatures.addAll(featureCollection);
        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));

        //检查公共点
        Feature mainFeature = getEditFeature();
        symbolHandler.checkBianjieBoundaryFeatureCommonPoint(mainFeature, featureCollection);
    }


    void addQiegePoint(LatLng latLng) {
        if (isFastDrag) {
            //消费快速拖拽问题
            isFastDrag = false;
            return;
        }
        Point point = Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude());
        storePointList.add(point);


        symbolHandler.clearPointSymbol();
        symbolHandler.createSymbol(latLng, storePointList.size() - 1);

        if (storePointList.size() > 1) {
            geoOpEditSource.setGeoJson(LineString.fromLngLats(storePointList));
        }

        historyOperationStack.push(new QiegeHistory(
                getEditFeature().getStringProperty(KEY_FEATURE_ID), latLng));
        undoHistoryOperationStack.clear();
    }

    void addWakongPoint(LatLng latLng) {
        if (isFastDrag) {
            //消费快速拖拽问题
            isFastDrag = false;
            return;
        }
        Point point = Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude());
        storePointList.add(point);

        symbolHandler.addPointSymbolOnWakong(
                getEditFeature().getStringProperty(KEY_FEATURE_ID), storePointList, point);


        List<Point> points = new ArrayList<>();
        points.addAll(storePointList);
        //闭合
        points.add(points.get(0));

        List<List<Point>> data = new ArrayList<>();
        data.add(points);

        geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));

        historyOperationStack.push(new WakongHistory(
                WakongHistory.Type.AddPoint,
                getEditFeature().getStringProperty(KEY_FEATURE_ID),
                storePointList.size() - 1, point));
        undoHistoryOperationStack.clear();
    }

    void addHebingFeature(Feature feature) {
        String featureId = feature.getStringProperty(KEY_FEATURE_ID);
        if (!storeFeatureIds.contains(featureId)) {
            storeFeatureIds.add(featureId);
            storeFeatureList.add(feature);

            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(storeFeatureList));
            historyOperationStack.push(new HebingHistory(
                    feature.getStringProperty(KEY_FEATURE_ID), feature));
            undoHistoryOperationStack.clear();
        }
    }

    void addShanchuFeature(Feature feature) {
        String featureId = feature.getStringProperty(KEY_FEATURE_ID);
        if (!storeFeatureIds.contains(featureId)) {
            storeFeatureIds.add(featureId);
            storeFeatureList.add(feature);

            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(storeFeatureList));
            historyOperationStack.push(new ShanchuHistory(
                    feature.getStringProperty(KEY_FEATURE_ID), feature));
            undoHistoryOperationStack.clear();
        }
    }


    public void clickSaveOperation() {
        if (drawModel == DrawType.Huizhi) {
            boolean hasResult = hasOpEditResult();
            if (hasResult) {
                baseView.showToast("绘制已完成");
                return;
            }
            if (geometryType == OpGeometryType.Polygon) {
                boolean isCheckBoundary = isCheckHuizhiBoundary();
                if (isCheckBoundary) {
                    doSaveHuizhiCheckBoundary();
                } else {
                    GeoOpSaveResult result = doSaveOperation(drawModel);
                    if (result != null) {
                        saveResultList.add(result);
                        if (opListener != null) {
                            opListener.onOpSaveResult(drawModel, result);
                        }
                    }
                }
            } else {
                GeoOpSaveResult result = doSaveOperation(drawModel);
                if (result != null) {
                    saveResultList.add(result);
                    if (opListener != null) {
                        opListener.onOpSaveResult(drawModel, result);
                    }
                }
            }
        }
        else if (drawModel == DrawType.Bianjie) {
            GeoOpSaveResult result = doSaveOperation(drawModel);
            if (result != null) {
                saveResultList.add(result);
                if (opListener != null) {
                    opListener.onOpSaveResult(drawModel, result);
                }
            }
        }
        else if (drawModel == DrawType.Qiege) {
            GeoOpSaveResult result = doSaveOperation(drawModel);
            if (result != null) {
                saveResultList.add(result);
                if (opListener != null) {
                    opListener.onOpSaveResult(drawModel, result);
                }
            }
        }
        else if (drawModel == DrawType.Wakong) {
            GeoOpSaveResult result = doSaveOperation(drawModel);
            if (result != null) {
                saveResultList.add(result);
                if (opListener != null) {
                    opListener.onOpSaveResult(drawModel, result);
                }
            }
        }
        else if (drawModel == DrawType.Hebing) {
            GeoOpSaveResult result = doSaveOperation(drawModel);
            if (result != null) {
                saveResultList.add(result);
                if (opListener != null) {
                    opListener.onOpSaveResult(drawModel, result);
                }
            }
        }
        else if (drawModel == DrawType.Shanchu) {
            GeoOpSaveResult result = doSaveOperation(drawModel);
            if (result != null) {
                saveResultList.add(result);
                if (opListener != null) {
                    opListener.onOpSaveResult(drawModel, result);
                }
            }
        }
    }

    public boolean isCheckHuizhiBoundary() {
        return true;
    }

    public boolean isAddCommonPointOnQiege() {
        return false;
    }

    public Observable<Geometry> dealGeometryDifference(Geometry geometry) {
        return Observable.create(new ObservableOnSubscribe<Geometry>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<Geometry> emitter) throws Exception {
                emitter.onNext(geometry);
                emitter.onComplete();
            }
        });
    }

    //是否确认新建图形边界与其他图形相交，该操作只能请求后台接口进行判断
    void doSaveHuizhiCheckBoundary() {
        if (storePointList.size() < 3) {
            baseView.showToast("至少需要三个点");
            return;
        }

        //查询绘制图形是否与其他图形相交
        List<Point> points = new ArrayList<>();
        points.addAll(storePointList);
        //闭合
        points.add(points.get(0));

        List<List<Point>> data = new ArrayList<>();
        data.add(points);

        baseView.showLoading();
        dealGeometryDifference(Polygon.fromLngLats(data))
                .compose(baseView.bindToLifecycle())
                .subscribe(new DisposableObserver<Geometry>() {
                    @Override
                    public void onNext(@NonNull Geometry geometry) {

                        setOpEditResult(Feature.fromGeometry(geometry));

                        storePointList.clear();
                        symbolHandler.clearAllSymbol();

                        historyOperationStack.clear();
                        undoHistoryOperationStack.clear();
                        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));

                        GeoOpSaveResult result = new GeoOpSaveResult();
                        saveResultList.add(result);
                        if (opListener != null) {
                            opListener.onOpSaveResult(drawModel, result);
                        }
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        baseView.hideLoading();
                        baseView.showToast(e.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        baseView.hideLoading();
                    }
                });
    }


    GeoOpSaveResult doSaveOperation(DrawType drawModel) {
        isFastDrag = false;
        if (drawModel == DrawType.Huizhi) {
            if (geometryType == OpGeometryType.Polygon) {
                if (storePointList.size() < 3) {
                    baseView.showToast("至少需要三个点");
                    return null;
                }
                List<Point> points = new ArrayList<>();
                points.addAll(storePointList);
                //闭合
                points.add(points.get(0));

                List<List<Point>> data = new ArrayList<>();
                data.add(points);

                setOpEditResult(Feature.fromGeometry(Polygon.fromLngLats(data)));
            } else if (geometryType == OpGeometryType.Line) {
                if (storePointList.size() < 2) {
                    baseView.showToast("至少需要两个点");
                    return null;
                }
                List<Point> points = new ArrayList<>();
                points.addAll(storePointList);
                setOpEditResult(Feature.fromGeometry(LineString.fromLngLats(points)));
            } else if (geometryType == OpGeometryType.Point) {
                if (storePointList.size() < 1) {
                    baseView.showToast("至少需要一个点");
                    return null;
                }
                Point point = storePointList.get(0);
                setOpEditResult(Feature.fromGeometry(point));
            }

            GeoOpSaveResult saveResult = new GeoOpSaveResult();
            storePointList.clear();
            symbolHandler.clearAllSymbol();

            historyOperationStack.clear();
            undoHistoryOperationStack.clear();
            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
            return saveResult;
        }
        else if (drawModel == DrawType.Bianjie) {
            GeoOpSaveResult saveResult = new GeoOpSaveResult();
            setOpEditResults(editFeatures);

            symbolHandler.clearAllSymbol();

            historyOperationStack.clear();
            undoHistoryOperationStack.clear();

            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
            return saveResult;
        }
        else if (drawModel == DrawType.Qiege) {
            if (storePointList.size() < 2) {
                baseView.showToast("请标绘出一条切割线");
                return null;
            }
            LineString sliceLine = LineString.fromLngLats(storePointList);

            GeometryHelper geometryHelper = new GeometryHelper();
            List<Geometry> geometries = new ArrayList<>();
            for (Feature feature : editFeatures) {
                geometries.add(feature.geometry());
            }

            if (geometryType == OpGeometryType.Polygon) {
                GeometryHelper.SlicePolygonByLineResult result =
                        geometryHelper.slicePolygonByLine(geometries, sliceLine);
                if (result != null && result.getResultPolygons().size() > 0) {

                    List<Feature> features = new ArrayList<>();
                    for (Polygon polygon : result.getResultPolygons()) {
                        features.add(Feature.fromGeometry(polygon));
                    }

                    //为编辑图形添加公共切割点
                    if (isAddCommonPointOnQiege() && result.getSlicePoints().size() > 0) {
                        features = doAddQiegeCommonPointToEditFeatures(features, result);
                    }
                    setOpEditResults(features);

                    GeoOpSaveResult saveResult = new GeoOpSaveResult();
                    storePointList.clear();
                    symbolHandler.clearPointSymbol();

                    historyOperationStack.clear();
                    undoHistoryOperationStack.clear();
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                    saveResult.addResultMetaData(GeoOpSaveResult.OP_SAVE_QIEGE_META_DATA, result);

                    if (isAddCommonPointOnQiege() && result.getSlicePoints().size() > 0) {
                        doAddQiegeCommonPointToCommonLineGeometry(getSelectedEditFeature(), result);
                    }

                    return saveResult;
                } else {
                    baseView.showToast("切割失败");
                    return null;
                }
            } else if (geometryType == OpGeometryType.Line) {
                List<LineString> result = geometryHelper.sliceLineStringByLine(geometries, sliceLine);
                if (result != null && result.size() > 0) {

                    List<Feature> features = new ArrayList<>();
                    for (LineString lineString : result) {
                        features.add(Feature.fromGeometry(lineString));
                    }
                    setOpEditResults(features);

                    GeoOpSaveResult saveResult = new GeoOpSaveResult();
                    storePointList.clear();
                    symbolHandler.clearPointSymbol();

                    historyOperationStack.clear();
                    undoHistoryOperationStack.clear();
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));

                    return saveResult;
                } else {
                    baseView.showToast("切割失败");
                    return null;
                }
            }
        }
        else if (drawModel == DrawType.Wakong) {
            if (storePointList.size() < 3) {
                baseView.showToast("请在图形内标绘出一个多边形");
                return null;
            }
            GeometryHelper geometryHelper = new GeometryHelper();

            Feature editFeature = getEditFeature();
            if (editFeature.geometry() instanceof MultiPolygon) {
                MultiPolygon multiPolygon = (MultiPolygon) editFeature.geometry();


                List<Geometry> geometries = new ArrayList<>();

                //将多多边形分割为多边形列表
                for (List<List<Point>> coordinates : multiPolygon.coordinates()) {
                    Geometry geometry = geometryHelper.hollowPolygon(
                            Polygon.fromLngLats(coordinates), storePointList);
                    if (geometry != null) {
                        geometries.add(geometry);
                    }
                }
                if (geometries.size() > 0) {
                    //将图形合并为多多边形
                    List<List<List<Point>>> coordinates = new ArrayList<>();
                    for (Geometry geometry : geometries) {

                        if (geometry instanceof MultiPolygon) {
                            coordinates.addAll(((MultiPolygon) geometry).coordinates());
                        } else if (geometry instanceof Polygon) {
                            coordinates.add(((Polygon) geometry).coordinates());
                        }
                    }

                    multiPolygon = MultiPolygon.fromLngLats(coordinates);
                    setOpEditResult(Feature.fromGeometry(multiPolygon));

                    GeoOpSaveResult saveResult = new GeoOpSaveResult();
                    storePointList.clear();
                    symbolHandler.clearAllSymbol();

                    historyOperationStack.clear();
                    undoHistoryOperationStack.clear();
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));


                    return saveResult;
                } else {
                    baseView.showToast("挖孔失败");
                    return null;
                }
            }
            else if (editFeature.geometry() instanceof Polygon) {

                Geometry geometry = geometryHelper.hollowPolygon(
                        (Polygon) editFeature.geometry(), storePointList);
                if (geometry != null) {

                    //将图形合并为多多边形
                    MultiPolygon multiPolygon;
                    if (geometry instanceof MultiPolygon) {
                        multiPolygon = (MultiPolygon) geometry;
                    } else {
                        multiPolygon = MultiPolygon.fromPolygon((Polygon) geometry);
                    }
                    setOpEditResult(Feature.fromGeometry(multiPolygon));

                    GeoOpSaveResult saveResult = new GeoOpSaveResult();
                    storePointList.clear();
                    symbolHandler.clearAllSymbol();

                    historyOperationStack.clear();
                    undoHistoryOperationStack.clear();
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));

                    return saveResult;
                } else {
                    baseView.showToast("挖孔失败");
                    return null;
                }
            }
        }
        else if (drawModel == DrawType.Hebing) {
            if (storeFeatureList.size() == 0) {
                baseView.showToast("请先选择至少一个图形");
                return null;
            }
            GeometryHelper geometryHelper = new GeometryHelper();
            List<Feature> originFeatures = new ArrayList<>(storeFeatureList);
            originFeatures.add(getEditFeature());

            List<Geometry> geometries = new ArrayList<>();
            //添加编辑的图形
            geometries.add(getEditFeature().geometry());
            //添加选中的图形
            for (Feature feature : storeFeatureList) {
                geometries.add(feature.geometry());
            }
            Geometry geometry = geometryHelper.unionGeometry(geometries);
            if (geometry != null) {
                Feature feature = Feature.fromGeometry(geometry);
                setOpEditResult(feature);


                GeoOpSaveResult saveResult = new GeoOpSaveResult();
                saveResult.deleteFeatureIds.addAll(storeFeatureIds);
                saveResult.setOriginFeatures(originFeatures);

                storeFeatureList.clear();
                storeFeatureIds.clear();
                historyOperationStack.clear();
                undoHistoryOperationStack.clear();
                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));

                return saveResult;

            } else {
                baseView.showToast("合并失败");
                return null;
            }
        }
        else if (drawModel == DrawType.Shanchu) {
            GeoOpSaveResult saveResult = new GeoOpSaveResult();
            saveResult.deleteFeatureIds.addAll(storeFeatureIds);

            historyOperationStack.clear();
            undoHistoryOperationStack.clear();
            return saveResult;
        }
        return null;
    }

    public void clickUndoOperation() {
        doUndoOperation();
    }

    //撤销操作
    void doUndoOperation() {
        isFastDrag = false;
        if (drawModel == DrawType.Huizhi) {
            if (historyOperationStack.size() == 0) {
                return;
            }
            HuizhiHistory huizhiHistory = (HuizhiHistory) historyOperationStack.pop();
            if (historyOperationStack != null && historyOperationStack.size() > 0) {
                if (huizhiHistory.getType() == HuizhiHistory.Type.AddPoint) {
                    storePointList.remove(storePointList.size() - 1);
                    symbolHandler.undoHuizhiAddPointOp(huizhiHistory, geometryType, storePointList);
                } else if (huizhiHistory.getType() == HuizhiHistory.Type.MovePoint) {
                    symbolHandler.updateGeometryHuizhiMovePoint(storePointList, huizhiHistory.getPointIndex(), huizhiHistory.getOldPoint(), true);
                    storePointList.set(huizhiHistory.getPointIndex(), huizhiHistory.getOldPoint());
                } else if (huizhiHistory.getType() == HuizhiHistory.Type.InsertPoint) {
                    int pointIndex = huizhiHistory.getPointIndex();
                    storePointList.remove(pointIndex);
                    symbolHandler.undoHuizhiInsertPoitOp(storePointList, pointIndex);
                }
            } else if (storePointList.size() > 0) {
                storePointList.clear();
                symbolHandler.clearPointSymbol();
            }

            if (geometryType == OpGeometryType.Polygon) {
                if (storePointList.size() > 1) {
                    List<Point> points = new ArrayList<>();
                    points.addAll(storePointList);
                    //闭合
                    points.add(points.get(0));

                    List<List<Point>> data = new ArrayList<>();
                    data.add(points);
                    geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));
                } else {
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                }
            } else if (geometryType == OpGeometryType.Line) {
                if (storePointList.size() > 1) {
                    List<Point> points = new ArrayList<>();
                    points.addAll(storePointList);

                    geoOpEditSource.setGeoJson(LineString.fromLngLats(points));
                } else {
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                }
            }
            undoHistoryOperationStack.push(huizhiHistory);
        }
        else if (drawModel == DrawType.Bianjie) {
            if (historyOperationStack != null && historyOperationStack.size() > 0) {
                OperationHistory history = historyOperationStack.pop();

                if (history instanceof BianjieHistory) {
                    BianjieHistory bianjieHistory = (BianjieHistory) history;

                    if (bianjieHistory.getType() == BianjieHistory.Type.MovePoint) {
                        doUndoBianjiMoveOperation(bianjieHistory);
                    } else if (bianjieHistory.getType() == BianjieHistory.Type.AddPoint) {
                        doUndoBianjieAddOperation(bianjieHistory);
                    } else if (bianjieHistory.getType() == BianjieHistory.Type.DeletePoint) {
                        doUndoBianjiDeleteOperation(bianjieHistory);
                    }
                } else if (history instanceof BianjieCommonHistory) {
                    //公共点历史
                    BianjieCommonHistory commonHistory = (BianjieCommonHistory) history;
                    if (commonHistory.getType() == BianjieHistory.Type.MovePoint) {
                        doUndoBianjiMoveOperation(commonHistory);
                    } else if (commonHistory.getType() == BianjieHistory.Type.AddPoint) {
                        doCommonBianjiDeleteOperation(commonHistory, getEditFeatureId());
                    } else if (commonHistory.getType() == BianjieHistory.Type.DeletePoint) {
                        doUndoBianjiDeleteOperation(commonHistory, getEditFeatureId());
                        symbolHandler.addCommonPoint(commonHistory);
                    }

                }
                undoHistoryOperationStack.push(history);
            }
        }
        else if (drawModel == DrawType.Qiege) {
            if (historyOperationStack != null && historyOperationStack.size() > 0) {
                OperationHistory history = historyOperationStack.peek();
                if (history instanceof QiegeHistory) {
                    QiegeHistory qiegeHistory = (QiegeHistory) history;
                    historyOperationStack.pop();
                    if (qiegeHistory.getType() == QiegeHistory.Type.AddPoint) {

                        storePointList.remove(storePointList.size() - 1);
                        symbolHandler.clearPointSymbol();

                        if (storePointList.size() > 1) {
                            geoOpEditSource.setGeoJson(LineString.fromLngLats(storePointList));
                        } else {
                            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                        }

                        if (storePointList.size() > 0) {
                            Point lastPoint = storePointList.get(storePointList.size() - 1);

                            symbolHandler.createSymbol(
                                    new LatLng(lastPoint.latitude(), lastPoint.longitude()),
                                    storePointList.size() - 1);
                        }
                    }
                    else if (qiegeHistory.getType() == QiegeHistory.Type.MovePoint) {
                        storePointList.remove(storePointList.size() - 1);

                        symbolHandler.clearPointSymbol();

                        QiegeHistory lastQiegeHistory = (QiegeHistory) historyOperationStack.peek();
                        LatLng latLng = lastQiegeHistory.getPoint();

                        Point point = Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude());
                        storePointList.add(point);

                        if (storePointList.size() > 1) {
                            geoOpEditSource.setGeoJson(LineString.fromLngLats(storePointList));
                        } else {
                            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                        }

                        if (storePointList.size() > 0) {
                            Point lastPoint = storePointList.get(storePointList.size() - 1);

                            symbolHandler.createSymbol(new LatLng(lastPoint.latitude(), lastPoint.longitude()),
                                    storePointList.size() - 1);
                        }
                    }
                }
                undoHistoryOperationStack.push(history);
            }
        }
        else if (drawModel == DrawType.Wakong) {
            if (historyOperationStack != null && historyOperationStack.size() > 0) {
                WakongHistory wakongHistory = (WakongHistory) historyOperationStack.pop();
                if (historyOperationStack.size() > 0) {
                    if (wakongHistory.getType() == WakongHistory.Type.AddPoint) {
                        storePointList.remove(storePointList.size() - 1);
                        symbolHandler.undoWakongAddPointOp(wakongHistory, storePointList);
                    } else if (wakongHistory.getType() == WakongHistory.Type.MovePoint) {
                        symbolHandler.updateGeometryWakongMovePoint(
                                storePointList, wakongHistory.getPointIndex(), wakongHistory.getOldPoint(), true);
                        storePointList.set(wakongHistory.getPointIndex(), wakongHistory.getOldPoint());
                    } else if (wakongHistory.getType() == WakongHistory.Type.InsertPoint) {
                        int pointIndex = wakongHistory.getPointIndex();
                        storePointList.remove(pointIndex);
                        symbolHandler.undoWakongInsertPoitOp(storePointList, pointIndex);
                    }
                } else if (storePointList.size() > 0) {
                    storePointList.clear();
                    symbolHandler.clearPointSymbol();
                }

                if (storePointList.size() > 2) {
                    List<Point> points = new ArrayList<>();
                    points.addAll(storePointList);
                    //闭合
                    points.add(points.get(0));

                    List<List<Point>> data = new ArrayList<>();
                    data.add(points);
                    geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));
                } else {
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                }

                undoHistoryOperationStack.push(wakongHistory);
            }
        }
        else if (drawModel == DrawType.Hebing) {
            if (historyOperationStack != null && historyOperationStack.size() > 0) {
                OperationHistory operationHistory = historyOperationStack.pop();

                Feature feature = storeFeatureList.remove(storeFeatureList.size() - 1);
                String featureId = feature.getStringProperty(KEY_FEATURE_ID);
                storeFeatureIds.remove(featureId);

                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(storeFeatureList));

                undoHistoryOperationStack.push(operationHistory);
            }
        }
        else if (drawModel == DrawType.Shanchu) {
            if (historyOperationStack != null && historyOperationStack.size() > 0) {
                OperationHistory operationHistory = historyOperationStack.pop();

                Feature feature = storeFeatureList.remove(storeFeatureList.size() - 1);
                String featureId = feature.getStringProperty(KEY_FEATURE_ID);
                storeFeatureIds.remove(featureId);

                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(storeFeatureList));

                undoHistoryOperationStack.push(operationHistory);
            }
        }
    }

    public void clickRedoOperation() {
        doRedoOperation();
    }

    //返回操作
    void doRedoOperation() {
        isFastDrag = false;
        if (drawModel == DrawType.Huizhi) {
            if (undoHistoryOperationStack.size() > 0) {
                HuizhiHistory huizhiHistory = (HuizhiHistory) undoHistoryOperationStack.pop();

                if (huizhiHistory.getType() == HuizhiHistory.Type.AddPoint) {
                    Point lastPoint = huizhiHistory.getNewPoint();

                    if (geometryType == OpGeometryType.Point) {
                        storePointList.clear();
                        symbolHandler.clearPointSymbol();
                    }
                    storePointList.add(lastPoint);

                    symbolHandler.addPointSymbolOnHuizhi(geometryType, storePointList, lastPoint);
                } else if (huizhiHistory.getType() == HuizhiHistory.Type.MovePoint) {
                    symbolHandler.updateGeometryHuizhiMovePoint(storePointList, huizhiHistory.getPointIndex(), huizhiHistory.getNewPoint(), true);
                    storePointList.set(huizhiHistory.getPointIndex(), huizhiHistory.getNewPoint());
                } else if (huizhiHistory.getType() == HuizhiHistory.Type.InsertPoint) {
                    doAddGeometrySymbolPointOnHuizhi(huizhiHistory.getPointIndex(), huizhiHistory.getNewPoint());
                }

                if (geometryType == OpGeometryType.Polygon) {
                    if (storePointList.size() > 1) {
                        List<Point> points = new ArrayList<>();
                        points.addAll(storePointList);
                        //闭合
                        points.add(points.get(0));

                        List<List<Point>> data = new ArrayList<>();
                        data.add(points);
                        geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));
                    } else {
                        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                    }
                } else if (geometryType == OpGeometryType.Line) {
                    if (storePointList.size() > 1) {
                        List<Point> points = new ArrayList<>();
                        points.addAll(storePointList);

                        geoOpEditSource.setGeoJson(LineString.fromLngLats(points));
                    } else {
                        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                    }
                }
                historyOperationStack.push(huizhiHistory);
            }
        } else if (drawModel == DrawType.Bianjie) {
            if (undoHistoryOperationStack != null && undoHistoryOperationStack.size() > 0) {
                OperationHistory history = undoHistoryOperationStack.pop();
                if (history instanceof BianjieHistory) {
                    BianjieHistory bianjieHistory = (BianjieHistory) history;

                    if (bianjieHistory.getType() == BianjieHistory.Type.MovePoint) {
                        doRedoBianjiMoveOperation(bianjieHistory);
                    } else if (bianjieHistory.getType() == BianjieHistory.Type.AddPoint) {
                        doRedoBianjieAddOperation(bianjieHistory);
                    } else if (bianjieHistory.getType() == BianjieHistory.Type.DeletePoint) {
                        doRedoBianjiDeleteOperation(bianjieHistory);
                    }
                } else if (history instanceof BianjieCommonHistory) {
                    //公共点历史
                    BianjieCommonHistory commonHistory = (BianjieCommonHistory) history;
                    if (commonHistory.getType() == BianjieHistory.Type.MovePoint) {
                        doRedoBianjiMoveOperation(commonHistory);
                    } else if (commonHistory.getType() == BianjieHistory.Type.AddPoint) {
                        doRedoBianjieAddOperation(commonHistory);
                    } else if (commonHistory.getType() == BianjieHistory.Type.DeletePoint) {
                        doCommonBianjiDeleteOperation(commonHistory, null);
                    }
                }
                historyOperationStack.push(history);
            }
        }
        else if (drawModel == DrawType.Qiege) {
            if (undoHistoryOperationStack.size() > 0) {
                OperationHistory history = undoHistoryOperationStack.peek();
                if (history instanceof  QiegeHistory) {
                    QiegeHistory qiegeHistory = (QiegeHistory) history;
                    undoHistoryOperationStack.pop();
                    if (qiegeHistory.getType() == QiegeHistory.Type.AddPoint) {
                        LatLng newPoint = qiegeHistory.getPoint();
                        storePointList.add(Point.fromLngLat(
                                newPoint.getLongitude(), newPoint.getLatitude()));

                        symbolHandler.clearPointSymbol();

                        if (storePointList.size() > 1) {
                            geoOpEditSource.setGeoJson(LineString.fromLngLats(storePointList));
                        } else {
                            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                        }

                        if (storePointList.size() > 0) {
                            Point lastPoint = storePointList.get(storePointList.size() - 1);

                            symbolHandler.createSymbol(new LatLng(lastPoint.latitude(), lastPoint.longitude()),
                                    storePointList.size() - 1);
                        }
                    } else if (qiegeHistory.getType() == QiegeHistory.Type.MovePoint) {
                        storePointList.remove(storePointList.size() - 1);

                        symbolHandler.clearPointSymbol();

                        LatLng latLng = qiegeHistory.getPoint();

                        Point point = Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude());
                        storePointList.add(point);

                        if (storePointList.size() > 1) {
                            geoOpEditSource.setGeoJson(LineString.fromLngLats(storePointList));
                        } else {
                            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                        }

                        if (storePointList.size() > 0) {
                            Point lastPoint = storePointList.get(storePointList.size() - 1);
                            symbolHandler.createSymbol(new LatLng(latLng.getLatitude(), lastPoint.longitude()),
                                    storePointList.size() - 1);

                        }
                    }
                    historyOperationStack.push(qiegeHistory);
                }
            }
        }
        else if (drawModel == DrawType.Wakong) {
            if (undoHistoryOperationStack.size() > 0) {
                WakongHistory wakongHistory = (WakongHistory) undoHistoryOperationStack.pop();
                if (historyOperationStack.size() > 0) {
                    if (wakongHistory.getType() == WakongHistory.Type.AddPoint) {

                        Point lastPoint = wakongHistory.getNewPoint();
                        storePointList.add(lastPoint);

                        symbolHandler.addPointSymbolOnWakong(wakongHistory.getFeatureId(), storePointList, lastPoint);
                    } else if (wakongHistory.getType() == WakongHistory.Type.MovePoint) {

                        symbolHandler.updateGeometryWakongMovePoint(storePointList, wakongHistory.getPointIndex(), wakongHistory.getNewPoint(), true);
                        storePointList.set(wakongHistory.getPointIndex(), wakongHistory.getNewPoint());
                    } else if (wakongHistory.getType() == WakongHistory.Type.InsertPoint) {
                        storePointList.add(wakongHistory.getPointIndex(), wakongHistory.getNewPoint());

                        symbolHandler.insertSymbolPointOnWakong(wakongHistory.getFeatureId(), storePointList,
                                wakongHistory.getPointIndex(), wakongHistory.getNewPoint());
                    }
                }

                if (storePointList.size() > 2) {
                    List<Point> points = new ArrayList<>();
                    points.addAll(storePointList);
                    //闭合
                    points.add(points.get(0));

                    List<List<Point>> data = new ArrayList<>();
                    data.add(points);
                    geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));
                } else {
                    geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
                }

                historyOperationStack.push(wakongHistory);
            }
        }
        else if (drawModel == DrawType.Hebing) {
            if (undoHistoryOperationStack.size() > 0) {
                HebingHistory hebingHistory = (HebingHistory) undoHistoryOperationStack.pop();

                storeFeatureList.add(hebingHistory.getChooseFeature());
                storeFeatureIds.add(hebingHistory.getFeatureId());

                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(storeFeatureList));

                historyOperationStack.push(hebingHistory);
            }
        } else if (drawModel == DrawType.Shanchu) {
            if (undoHistoryOperationStack != null && undoHistoryOperationStack.size() > 0) {
                ShanchuHistory shanchuHistory = (ShanchuHistory) undoHistoryOperationStack.pop();

                storeFeatureList.add(shanchuHistory.getChooseFeature());
                storeFeatureIds.add(shanchuHistory.getFeatureId());

                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(storeFeatureList));

                historyOperationStack.push(shanchuHistory);
            }
        }
    }

    public void clickClearOperation() {
        doClearOperation();
        if (opListener != null) {
            opListener.onOpSaveResult(drawModel, null);
        }
    }

    //清除操作
    void doClearOperation() {
        isFastDrag = false;
        if (drawModel == DrawType.Huizhi) {
            setOpEditResult(null);

            storePointList.clear();
            symbolHandler.clearAllSymbol();

            historyOperationStack.clear();
            undoHistoryOperationStack.clear();

            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));

        } else if (drawModel == DrawType.Bianjie) {
            symbolHandler.clearAllSymbol();
            historyOperationStack.clear();
            undoHistoryOperationStack.clear();

            symbolHandler.clearCommonPointData();

            addBianjieFeature(selectedEditFeature);
        } else if (drawModel == DrawType.Qiege) {
            if (historyOperationStack.size() > 0) {
                //重置当前切割线
                historyOperationStack.clear();
                undoHistoryOperationStack.clear();

                storePointList.clear();
                symbolHandler.clearPointSymbol();

                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
            } else {
                //重置当前结果集
                setOpEditResult(null);
                setEditFeature(selectedEditFeature);
            }
        } else if (drawModel == DrawType.Wakong) {
            if (historyOperationStack.size() > 0) {
                historyOperationStack.clear();
                undoHistoryOperationStack.clear();

                storePointList.clear();
                symbolHandler.clearAllSymbol();

                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
            } else {
                //重置当前结果集
                setOpEditResult(null);
                setEditFeature(selectedEditFeature);
            }
        } else if (drawModel == DrawType.Hebing) {
            if (historyOperationStack.size() > 0) {
                historyOperationStack.clear();
                undoHistoryOperationStack.clear();

                storeFeatureIds.clear();
                storeFeatureList.clear();

                geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));
            } else {
                //重置当前结果集
                setOpEditResult(null);
                setEditFeature(selectedEditFeature);
            }
        } else if (drawModel == DrawType.Shanchu) {
            historyOperationStack.clear();
            undoHistoryOperationStack.clear();

            storeFeatureIds.clear();
            storeFeatureList.clear();
            geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(new ArrayList<>()));

        }
    }

    //撤销移动边界
    private void doUndoBianjiMoveOperation(BianjieCommonHistory commonHistory) {
        for (BianjieHistory history : commonHistory.getBianjieHistories()) {
            String targetFeatureId = history.getFeatureTempId();
            int [] coordinatesIndex = history.getCoordinatesIndex();
            LatLng oldPoint = new LatLng(history.getOldPoint().latitude(),
                    history.getOldPoint().longitude());
            Feature opFeature = getEditFeature(targetFeatureId);

            symbolHandler.updateGeometryCoordinatesLatlng(targetFeatureId, coordinatesIndex, oldPoint, true);
            symbolHandler.updateGeometryPointSymbolOnBianjieMove(opFeature, coordinatesIndex);
        }

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }


    //撤销移动边界
    private void doUndoBianjiMoveOperation(BianjieHistory history) {
        String targetFeatureId = history.getFeatureTempId();
        int [] coordinatesIndex = history.getCoordinatesIndex();
        LatLng oldPoint = new LatLng(history.getOldPoint().latitude(),
                history.getOldPoint().longitude());
        Feature opFeature = getEditFeature(targetFeatureId);

        symbolHandler.updateGeometryCoordinatesLatlng(targetFeatureId, coordinatesIndex, oldPoint, true);
        symbolHandler.updateGeometryPointSymbolOnBianjieMove(opFeature, coordinatesIndex);

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    //撤销新增边界
    private void doUndoBianjieAddOperation(BianjieHistory history) {
        String targetFeatureId = history.getFeatureTempId();
        int [] coordinatesIndex = history.getCoordinatesIndex();

        //找出i,j这个列表下所有大于k的symbol，将索引减1
        symbolHandler.deleteGeometrySymbolDataIndexs(targetFeatureId, coordinatesIndex, true);

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    //撤销删除边界
    private void doUndoBianjiDeleteOperation(BianjieHistory history) {
        int[] coordinates = history.getCoordinatesIndex();
        symbolHandler.addPointDataIndexs(history.getFeatureTempId(), coordinates, history.getOldPoint());
        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    //撤销删除边界
    private void doUndoBianjiDeleteOperation(BianjieCommonHistory commonHistory, String targetFeatureId) {
        String commonKey = commonHistory.getCommonKey();
        for (BianjieHistory history : commonHistory.getBianjieHistories()) {
            int[] coordinates = history.getCoordinatesIndex();
            if (history.getFeatureTempId().equals(targetFeatureId)) {
                //只对操作的图像添加一个共点，其他不重复添加
                symbolHandler.addPointDataIndexs(history.getFeatureTempId(), coordinates, history.getOldPoint(), true, commonKey);
            } else {
                symbolHandler.addPointDataIndexs(history.getFeatureTempId(), coordinates, history.getOldPoint(), false, commonKey);
            }
        }
        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }


    private void doRedoBianjiMoveOperation(BianjieCommonHistory commonHistory) {
        for (BianjieHistory history : commonHistory.getBianjieHistories()) {
            String targetFeatureId = history.getFeatureTempId();
            int [] coordinatesIndex = history.getCoordinatesIndex();
            LatLng newPoint = new LatLng(history.getNewPoint().latitude(),
                    history.getNewPoint().longitude());
            Feature opFeature = getEditFeature(targetFeatureId);

            symbolHandler.updateGeometryCoordinatesLatlng(
                    targetFeatureId, coordinatesIndex, newPoint, true);
            symbolHandler.updateGeometryPointSymbolOnBianjieMove(opFeature, coordinatesIndex);
        }

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    private void doRedoBianjiMoveOperation(BianjieHistory history) {
        String targetFeatureId = history.getFeatureTempId();
        int [] coordinatesIndex = history.getCoordinatesIndex();
        LatLng newPoint = new LatLng(history.getNewPoint().latitude(),
                history.getNewPoint().longitude());
        Feature opFeature = getEditFeature(targetFeatureId);

        symbolHandler.updateGeometryCoordinatesLatlng(
                targetFeatureId, coordinatesIndex, newPoint, true);
        symbolHandler.updateGeometryPointSymbolOnBianjieMove(opFeature, coordinatesIndex);

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    private void doRedoBianjieAddOperation(BianjieCommonHistory commonHistory) {
        for (BianjieHistory history : commonHistory.getBianjieHistories()) {
            int[] coordinates = history.getCoordinatesIndex();
            symbolHandler.addPointDataIndexs(history.getFeatureTempId(), coordinates, history.getNewPoint());
        }

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    private void doRedoBianjieAddOperation(BianjieHistory history) {
        int[] coordinates = history.getCoordinatesIndex();
        symbolHandler.addPointDataIndexs(history.getFeatureTempId(), coordinates, history.getNewPoint());

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    private void doRedoBianjiDeleteOperation(BianjieHistory history) {
        String targetFeatureId = history.getFeatureTempId();
        int[] coordinates = history.getCoordinatesIndex();
        symbolHandler.deleteGeometrySymbolDataIndexs(targetFeatureId, coordinates, true);

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    private void doCommonBianjiDeleteOperation(BianjieCommonHistory commonHistory, String targetFeatureId) {
        for (BianjieHistory history : commonHistory.getBianjieHistories()) {
            int[] coordinates = history.getCoordinatesIndex();
            if (StringUtils.isNotEmpty(targetFeatureId)) {
                if (history.getFeatureTempId().equals(targetFeatureId)) {
                    symbolHandler.deleteGeometrySymbolDataIndexs(history.getFeatureTempId(), coordinates, true);
                } else {
                    symbolHandler.deleteGeometrySymbolDataIndexs(history.getFeatureTempId(), coordinates, false);
                }
            } else {
                symbolHandler.deleteGeometrySymbolDataIndexs(history.getFeatureTempId(), coordinates, true);
            }
        }
        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));

        String commonKey = commonHistory.getCommonKey();
        symbolHandler.removeCommonPoint(commonKey);
    }

    private List<Feature> doAddQiegeCommonPointToEditFeatures(List<Feature> features,
                                                     GeometryHelper.SlicePolygonByLineResult result) {
        GeometryHelper geometryHelper = new GeometryHelper();

        Map<String, Feature> featureMap = new HashMap<>();
        for (Feature feature : features) {
            String featureId = StringUtils.generateId();
            feature.addStringProperty(KEY_FEATURE_TEMP_ID, featureId);
            Polygon polygon = (Polygon) feature.geometry();
            featureMap.put(featureId, feature);
        }

        //记录每个图形添加的共点，避免重复添加多个相同共点
        Map<String, Set<String>> geometryAddPointRecord = new HashMap<>();
        for (int i = 0; i < features.size(); i++) {
            Feature featureI = features.get(i);
            String featureId = featureI.getStringProperty(KEY_FEATURE_ID);
            Set<String> pointIdSet = null;
            if (!geometryAddPointRecord.containsKey(featureId)) {
                pointIdSet = new HashSet<>();
                geometryAddPointRecord.put(featureId, pointIdSet);
            } else {
                pointIdSet = geometryAddPointRecord.get(featureId);
            }

            for (int j = 0; j < features.size(); j++) {
                Feature featureJ = features.get(j);
                if (i == j) {
                    continue;
                }

                boolean isTouches = geometryHelper.intersection(
                        featureI.geometry(), featureJ.geometry()) != null;
                if (isTouches) {
                    Geometry geometryResult = featureJ.geometry();
                    for (GeometryHelper.SlicePoint slicePoint : result.getSlicePoints()) {
                        if (pointIdSet.contains(slicePoint.getId())) {
                            //不重复添加
                            continue;
                        }
                        //判断切割点线段是否和该图形是公共边
                        Geometry geometryIntersection = geometryHelper.intersection(
                                geometryResult, slicePoint.getIntersectionLine());
                        if (geometryIntersection instanceof LineString) {
                            //说明有切割点线段是该图形的一条公共线段
                            LineString intersectionLine = (LineString) geometryIntersection;
                            Point point1Start = slicePoint.getIntersectionLine().coordinates().get(0);
                            Point point1End = slicePoint.getIntersectionLine().coordinates().get(1);

                            Point point2Start = intersectionLine.coordinates().get(0);
                            Point point2End = intersectionLine.coordinates().get(1);

                            if ((point1Start.equals(point2Start) && point1End.equals(point2End))
                                    || (point1Start.equals(point2End) && point1End.equals(point2Start)) ) {
                                //两条线完全一致
                                geometryResult = addCommonPointToCommonGeometry(
                                        geometryResult, slicePoint);
                                pointIdSet.add(slicePoint.getId());
                            }
                        }
                    }

                    //更新图形
                    featureMap.put(featureJ.getStringProperty(KEY_FEATURE_TEMP_ID),
                            Feature.fromGeometry(geometryResult, featureJ.properties()));
                }

            }
        }

        return new ArrayList<>(featureMap.values());
    }
    //切割保存时，给其他公共边图形添加公共切割点
    List<Feature> addQiegeCommonPointFeatureList = new ArrayList<>();
    private void doAddQiegeCommonPointToCommonLineGeometry(
            Feature qiegeFeature,
            GeometryHelper.SlicePolygonByLineResult result) {
        Observable<Feature> observable = queryCommonPointGeometry(qiegeFeature)
                .map(new Function<Feature, Feature>() {
                    @Override
                    public Feature apply(@NonNull Feature feature) throws Exception {
                        //深复制
                        Feature copy = Feature.fromJson(MapboxJsonHelper.featureToJson(feature));
                        return copy;
                    }
                });
        if (observable != null) {
            addQiegeCommonPointFeatureList.clear();
            observable.subscribe(new DisposableObserver<Feature>() {
                @Override
                public void onNext(@NonNull Feature feature) {
                    Geometry geometry = feature.geometry();
                    GeometryHelper geometryHelper = new GeometryHelper();
                    for (GeometryHelper.SlicePoint slicePoint : result.getSlicePoints()) {
                        //判断切割点线段是否和该图形是公共边
                        Geometry geometryIntersection = geometryHelper.intersection(
                                geometry, slicePoint.getIntersectionLine());
                        if (geometryIntersection instanceof LineString) {
                            //说明有切割点线段是该图形的一条公共线段

                            LineString intersectionLine = (LineString) geometryIntersection;
                            Point point1Start = slicePoint.getIntersectionLine().coordinates().get(0);
                            Point point1End = slicePoint.getIntersectionLine().coordinates().get(1);

                            Point point2Start = intersectionLine.coordinates().get(0);
                            Point point2End = intersectionLine.coordinates().get(1);

                            if ((point1Start.equals(point2Start) && point1End.equals(point2End))
                                    || (point1Start.equals(point2End) && point1End.equals(point2Start)) ) {
                                //两条线完全一致
                                Geometry geometryResult = addCommonPointToCommonGeometry(geometry, slicePoint);

                                addQiegeCommonPointFeatureList.add(Feature.fromGeometry(
                                        geometryResult, feature.properties()));
                            }
                        }
                    }
                }

                @Override
                public void onError(@NonNull Throwable e) {
                    e.printStackTrace();
                }

                @Override
                public void onComplete() {
                    addOpEditResults(addQiegeCommonPointFeatureList);

                    addQiegeCommonPointFeatureList.clear();
                }
            });
        }
    }


    private Geometry addCommonPointToCommonGeometry(Geometry geometry, GeometryHelper.SlicePoint slicePoint) {
        List<Point> coordinates = null;
        GeometryHelper geometryHelper = new GeometryHelper();
        if (geometry instanceof MultiPolygon) {
            MultiPolygon multiPolygon = (MultiPolygon) geometry;

            for (List<List<Point>> lists : multiPolygon.coordinates()) {
                Polygon polygon = Polygon.fromLngLats(lists);
                //拆分MultiPolygon找到公共边的Polygon的坐标
                Geometry geometryIntersection = geometryHelper.intersection(
                        polygon, slicePoint.getIntersectionLine());
                if (geometryIntersection instanceof LineString) {
                    coordinates = polygon.coordinates().get(0);
                }
            }
        } else if (geometry instanceof Polygon) {
            Polygon polygon = (Polygon) geometry;
            coordinates = polygon.coordinates().get(0);
        }
        if (coordinates == null) {
            return geometry;
        }


        Point intersectionLinePoint1 = slicePoint.getIntersectionLine().coordinates().get(0);
        Point intersectionLinePoint2 = slicePoint.getIntersectionLine().coordinates().get(1);
        List<Integer> pointIndexList = new ArrayList<>();


        for (int i = 0; i < coordinates.size(); i++) {
            Point point = coordinates.get(i);
            double longitude = point.longitude();
            double latitude = point.latitude();
            if (longitude == intersectionLinePoint1.longitude()
                    && latitude == intersectionLinePoint1.latitude()) {
                pointIndexList.add(i);
                if (pointIndexList.size() == 2) {
                    break;
                }
            } else if (longitude == intersectionLinePoint2.longitude()
                    && latitude == intersectionLinePoint2.latitude()) {
                pointIndexList.add(i);
                if (pointIndexList.size() == 2) {
                    break;
                }
            }
        }
        if (pointIndexList.size() >= 2) {
            Collections.sort(pointIndexList);
            int startIndex = pointIndexList.get(0);
            int endIndex = pointIndexList.get(1);
            int insertIndex = -1;
            if (startIndex == 0 && endIndex < coordinates.size() - 1) {
                //说明是在末尾处切割
                insertIndex = endIndex + 1;
            } else if (startIndex + 1 == endIndex) {
                //说明两点间没有其他点
                //直接插入两点直接
                insertIndex = endIndex;
            } else {
                //两点间有其他点
                //从startIndex开始往后寻找相交线
                for (int i = startIndex + 1; i < endIndex; i++) {
                    List<Point> points = new ArrayList<>();
                    points.add(coordinates.get(startIndex));
                    points.add(coordinates.get(endIndex));

                    Geometry geometryIntersection = geometryHelper.intersection(
                            LineString.fromLngLats(points), slicePoint.getSliceLine());
                    if (geometryIntersection == null) {
                        //不想交，退出循环并往前移动
                        insertIndex = startIndex + 1;
                        break;
                    }
                }
            }
            if (insertIndex >= 0) {
                coordinates.add(insertIndex, slicePoint.getSlicePoint());
            }
        }

        return geometry;
    }

    public void doCloseOperation() {
        exitDrawModel();
    }


    public GeoSubmitResult doSubmitOperation() {
        if (saveResultList.size() > 0) {
            GeoSubmitResult submitResult = new GeoSubmitResult(
                    drawModel, getSelectedEditFeature(),
                    editFeatures, saveResultList);
            return submitResult;
        } else {
            baseView.showToast("没有保存结果");
        }
        return null;
    }


    private long dragStartTimeMillis;
    private boolean isFastDrag = false;
    //正在长按
    private boolean isOnLongPress = false;
    //记录拖拽前的经纬度
    private LatLng dragStartLatlng;
    //长按中的Symbol
    private Symbol longClickSymbol;


    @Override
    public void onAnnotationDragStarted(Symbol annotation) {
        dragStartTimeMillis = System.currentTimeMillis();
        dragStartLatlng = new LatLng(annotation.getLatLng().getLatitude(),
                annotation.getLatLng().getLongitude());
    }

    @Override
    public void onAnnotationDrag(Symbol annotation) {

    }

    @Override
    public void onAnnotationDragFinished(Symbol annotation) {
        if (isOnLongPress) {
            //消费事件
            isOnLongPress = false;
            return;
        }

        int symbolType = GeometrySymbolHandler.TYPE_SYMBOL_POINT;
        JsonObject jsonData = null;
        if (annotation.getData() != null) {
            jsonData = (JsonObject) annotation.getData();
        }
        if (jsonData.has(GeometrySymbolHandler.KEY_SYMBOL_TYPE)) {
            symbolType = jsonData.get(GeometrySymbolHandler.KEY_SYMBOL_TYPE).getAsInt();
        }

        long dragTime = System.currentTimeMillis() - dragStartTimeMillis;

        if (symbolType == GeometrySymbolHandler.TYPE_SYMBOL_POINT) {
            if (getDrawModel() == DrawType.Huizhi) {
                if (dragTime < 250) {
                    //因为快速拖拽会与onMapClick冲突，所以拖拽时长才算
                    isFastDrag = true;
                }

                String indexStr = jsonData.get(CommonPointHelper.KEY_POINT_INDEXS).getAsString();
                if (StringUtils.isNotEmpty(indexStr)) {
                    int coordinatesIndex = Integer.parseInt(indexStr);
                    Point oldPoint = storePointList.get(coordinatesIndex);
                    Point newPoint = Point.fromLngLat(annotation.getLatLng().getLongitude(),
                            annotation.getLatLng().getLatitude());

                    symbolHandler.updateGeometryHuizhiMovePoint(storePointList, coordinatesIndex, newPoint, false);

                    storePointList.set(coordinatesIndex, newPoint);

                    if (geometryType == OpGeometryType.Polygon) {
                        List<Point> points = new ArrayList<>();
                        points.addAll(storePointList);
                        //闭合
                        points.add(points.get(0));

                        List<List<Point>> data = new ArrayList<>();
                        data.add(points);

                        geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));
                    } else if (geometryType == OpGeometryType.Line) {
                        List<Point> points = new ArrayList<>();
                        points.addAll(storePointList);

                        geoOpEditSource.setGeoJson(LineString.fromLngLats(points));
                    } else if (geometryType == OpGeometryType.Point) {

                    }

                    HuizhiHistory huizhiHistory = new HuizhiHistory(HuizhiHistory.Type.MovePoint, coordinatesIndex, newPoint);
                    huizhiHistory.setOldPoint(oldPoint);
                    historyOperationStack.push(huizhiHistory);

                    undoHistoryOperationStack.clear();
                }

            }
            else if (getDrawModel() == DrawType.Bianjie) {
                onGeometryBianjieDrag(annotation);
            }
            else if (getDrawModel() == DrawType.Qiege) {
                if (dragTime < 250) {
                    //因为快速拖拽会与onMapClick冲突，所以拖拽时长才算
                    isFastDrag = true;
                }

                storePointList.remove(storePointList.size() -1);

                LatLng latLng = annotation.getLatLng();
                Point point = Point.fromLngLat(latLng.getLongitude(), latLng.getLatitude());
                storePointList.add(point);


                if (storePointList.size() > 1) {
                    geoOpEditSource.setGeoJson(LineString.fromLngLats(storePointList));
                }

                historyOperationStack.push(new QiegeHistory(
                        getEditFeature().getStringProperty(KEY_FEATURE_ID), latLng,
                        QiegeHistory.Type.MovePoint));

                undoHistoryOperationStack.clear();
            }
            else if (getDrawModel() == DrawType.Wakong) {
                if (dragTime < 250) {
                    //因为快速拖拽会与onMapClick冲突，所以拖拽时长才算
                    isFastDrag = true;
                }

                String indexStr = jsonData.get(CommonPointHelper.KEY_POINT_INDEXS).getAsString();
                if (StringUtils.isNotEmpty(indexStr)) {
                    int coordinatesIndex = Integer.parseInt(indexStr);
                    Point oldPoint = storePointList.get(coordinatesIndex);
                    Point newPoint = Point.fromLngLat(annotation.getLatLng().getLongitude(),
                            annotation.getLatLng().getLatitude());

                    symbolHandler.updateGeometryWakongMovePoint(storePointList, coordinatesIndex, newPoint, false);

                    storePointList.set(coordinatesIndex, newPoint);

                    List<Point> points = new ArrayList<>();
                    points.addAll(storePointList);
                    //闭合
                    points.add(points.get(0));

                    List<List<Point>> data = new ArrayList<>();
                    data.add(points);

                    geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));

                    WakongHistory history = new WakongHistory(
                            WakongHistory.Type.MovePoint,
                            getEditFeature().getStringProperty(KEY_FEATURE_ID), Integer.parseInt(indexStr),
                            newPoint);
                    history.setOldPoint(oldPoint);
                    historyOperationStack.push(history);
                    undoHistoryOperationStack.clear();
                }

            }
        } else if (symbolType == GeometrySymbolHandler.TYPE_SYMBOL_POINT_ADD) {
            if (dragTime < 250) {
                //因为快速拖拽会与onMapClick冲突，所以拖拽时长才算
                isFastDrag = true;
            }
            if (getDrawModel() == DrawType.Huizhi) {
                int insertIndex = Integer.parseInt(
                        ((JsonObject) annotation.getData())
                                .get(CommonPointHelper.KEY_POINT_INDEXS).getAsString());
                Point insertPoint = Point.fromLngLat(annotation.getLatLng().getLongitude(),
                        annotation.getLatLng().getLatitude());
                doAddGeometrySymbolPointOnHuizhi(insertIndex, insertPoint);

                HuizhiHistory history = new HuizhiHistory(HuizhiHistory.Type.InsertPoint, insertIndex, insertPoint);
                historyOperationStack.push(history);
                undoHistoryOperationStack.clear();
            }
            else if (getDrawModel() == DrawType.Bianjie) {
                doAddGeometrySymbolPointOnBianjie(annotation);
            }
            else if (getDrawModel() == DrawType.Wakong) {
                JsonObject jsonObject = (JsonObject) annotation.getData();
                String tempId = jsonObject.get(KEY_FEATURE_ID).getAsString();
                int insertIndex = Integer.parseInt(jsonObject.get(CommonPointHelper.KEY_POINT_INDEXS).getAsString());
                Point insertPoint = Point.fromLngLat(annotation.getLatLng().getLongitude(),
                        annotation.getLatLng().getLatitude());

                storePointList.add(insertIndex, insertPoint);

                symbolHandler.insertSymbolPointOnWakong(
                        tempId, storePointList, insertIndex, insertPoint);


                List<Point> points = new ArrayList<>();
                points.addAll(storePointList);
                //闭合
                points.add(points.get(0));

                List<List<Point>> data = new ArrayList<>();
                data.add(points);

                geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));

                WakongHistory history = new WakongHistory(
                        WakongHistory.Type.InsertPoint, tempId, insertIndex, insertPoint);
                historyOperationStack.push(history);
                undoHistoryOperationStack.clear();
            }
        }

    }

    @Override
    public boolean onAnnotationLongClick(Symbol symbol) {
        longClickSymbol = symbol;
        int symbolType = GeometrySymbolHandler.TYPE_SYMBOL_POINT;
        JsonObject jsonData = null;
        if (symbol.getData() != null) {
            jsonData = (JsonObject) symbol.getData();
        }
        if (jsonData.has(GeometrySymbolHandler.KEY_SYMBOL_TYPE)) {
            symbolType = jsonData.get(GeometrySymbolHandler.KEY_SYMBOL_TYPE).getAsInt();
        }
        if (symbolType == GeometrySymbolHandler.TYPE_SYMBOL_POINT) {
            if (drawModel == DrawType.Bianjie &&
                    (geometryType == OpGeometryType.Line || geometryType == OpGeometryType.Polygon)) {
                if (dragStartLatlng != null) {
                    double distance = TurfMeasurement.distance(Point.fromLngLat(
                            symbol.getLatLng().getLongitude(), symbol.getLatLng().getLatitude()),
                            Point.fromLngLat(dragStartLatlng.getLongitude(), dragStartLatlng.getLatitude()));

                    double zoom = mMapboxMap.getCameraPosition().zoom;
                    double scale = distance * 100 / zoom;

                    //当拖动记录过大时就不判断是长按情况
                    if (scale > 80) {
                        return true;
                    }
                }
                SimpleDialog dialog = new SimpleDialog(baseView.getContext())
                        .setMessage("是否删除该点？")
                        .setCancel("取消", new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                if (dragStartLatlng != null) {
                                    longClickSymbol.setLatLng(dragStartLatlng);
                                    symbolHandler.updateSymbol(longClickSymbol);
                                }
                            }
                        })
                        .setConfirm("确定", new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                if (geometryType == OpGeometryType.Line){
                                    doDeleteGeometrySymbolPoint(longClickSymbol);
                                } else if (geometryType == OpGeometryType.Polygon) {
                                    doDeleteGeometrySymbolPoint(longClickSymbol);
                                }
                            }
                        });
                dialog.setCancelable(false);
                dialog.show();
                isOnLongPress = true;
                return true;
            }
        } else if (symbolType == GeometrySymbolHandler.TYPE_SYMBOL_POINT_ADD) {
            return true;
        }
        return false;
    }

    private void onGeometryBianjieDrag(Symbol annotation) {
        JsonObject data = (JsonObject) annotation.getData();
        String tempId = data.get(KEY_FEATURE_ID).getAsString();
        String indexStr = data.get(CommonPointHelper.KEY_POINT_INDEXS).getAsString();
        String[] indexs = indexStr.split("-");
        int[] coordinatesIndex = new int[indexs.length];
        for (int i = 0; i < indexs.length; i++) {
            coordinatesIndex[i] = Integer.parseInt(indexs[i]);
        }

        //找到操作的Feature
        Feature operationFeature = getEditFeature(tempId);

        //移动点
        String commonKey = data.has(CommonPointHelper.COMMON_KEY) ?
                data.get(CommonPointHelper.COMMON_KEY).getAsString() : null;

        OperationHistory history;
        if (StringUtils.isNotEmpty(commonKey)) {
            history = symbolHandler.updateGeometryCoordinatesLatlng(annotation.getLatLng(), commonKey);
        } else {
            history = symbolHandler.updateGeometryCoordinatesLatlng(tempId, coordinatesIndex, annotation.getLatLng(), false);
        }
        symbolHandler.updateGeometryPointSymbolOnBianjieMove(operationFeature, coordinatesIndex);
        historyOperationStack.push(history);
        undoHistoryOperationStack.clear();

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    private void doDeleteGeometrySymbolPoint(Symbol symbol) {
        OperationHistory history = symbolHandler.doDeleteGeometrySymbolPoint(symbol, dragStartLatlng);
        if (history != null) {
            historyOperationStack.push(history);
        }

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }


    private void doAddGeometrySymbolPointOnHuizhi(int insertIndex, Point insertPoint) {
        storePointList.add(insertIndex, insertPoint);

        symbolHandler.insertSymbolPointOnHuizhi(storePointList, insertIndex, insertPoint);


        if (geometryType == OpGeometryType.Polygon) {
            List<Point> points = new ArrayList<>();
            points.addAll(storePointList);
            //闭合
            points.add(points.get(0));

            List<List<Point>> data = new ArrayList<>();
            data.add(points);

            geoOpEditSource.setGeoJson(Polygon.fromLngLats(data));
        } else if (geometryType == OpGeometryType.Line) {
            geoOpEditSource.setGeoJson(LineString.fromLngLats(new ArrayList<>(storePointList)));
        }
    }



    private void doAddGeometrySymbolPointOnBianjie(Symbol annotation) {
        JsonObject data = (JsonObject) annotation.getData();
        String tempId = data.get(KEY_FEATURE_ID).getAsString();
        String indexStr = data.get(CommonPointHelper.KEY_POINT_INDEXS).getAsString();
        String[] indexs = indexStr.split("-");
        int[] coordinatesIndex = new int[indexs.length];
        for (int i = 0; i < indexs.length; i++) {
            coordinatesIndex[i] = Integer.parseInt(indexs[i]);
        }

        Point insertPoint = Point.fromLngLat(annotation.getLatLng().getLongitude(),
                annotation.getLatLng().getLatitude());

        //插入新点
        OperationHistory history = symbolHandler.addPointDataIndexs(tempId, coordinatesIndex, insertPoint);
        historyOperationStack.push(history);
        undoHistoryOperationStack.clear();

        geoOpEditSource.setGeoJson(FeatureCollection.fromFeatures(editFeatures));
    }

    public void release() {
        symbolHandler.release();
    }

    private class BianjieCommonPointObserver extends DisposableObserver<Feature> {

        List<Feature> commonPointFeatureList = new ArrayList<>();

        @Override
        public void onNext(@NonNull Feature feature) {
            commonPointFeatureList.add(feature);
        }

        @Override
        public void onError(@NonNull Throwable e) {
            baseView.showToast("查询公共点失败");
        }

        @Override
        public void onComplete() {
            addBianjieBoundaryFeature(commonPointFeatureList);
        }
    }

}